package filter;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.AttributeKey;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

import javax.imageio.ImageIO;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import log.ServerLogger;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import util.DataConvert;
import util.NumberUtil;
import xml.RequestBody;




//public class MyTextDecoder implements ProtocolDecoder
public class MyTextDecoder extends CumulativeProtocolDecoder
{
	//存放断包数据   
	private final AttributeKey BUFFER = new AttributeKey(getClass(), "buffer");  
	private IoBuffer buff = IoBuffer.allocate(2048).setAutoExpand(true);
	/*
	public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out)
			throws Exception
	{

		boolean complete = false;
		while (in.hasRemaining()) {
			byte b = in.get();

			// CIMConstant.MESSAGE_SEPARATE 为消息界限
			// 当一次收到多个消息时，以此分隔解析多个消息

			if (b == '\b') {
				complete = true;
				break;
			} else {
				buff.put(b);
			}
		}
		if (complete) {
			buff.flip();
			byte[] bytes = new byte[buff.limit()];
			buff.get(bytes);
			String message = new String(bytes, "UTF-8");
			buff.clear();
			if((message.startsWith("<?xml version=\"1.0\"")))
			{
				Object msgObject = mappingMessageObject(message);
				out.write(msgObject);
			}else
			{
				ServerLogger.Error("客户端发送协议不标准:"+message);
			}
		}


	}
	 */
	/*
	protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {

		boolean complete = false;
		while (in.remaining()>0) {
			byte b = in.get();

			// CIMConstant.MESSAGE_SEPARATE 为消息界限
			// 当一次收到多个消息时，以此分隔解析多个消息

			if (b == '\b') {

				complete = true;
				if(in.remaining()>0)
				{
					return true;
				}
				break;
			} else {
				buff.put(b);
			}
		}
		if (complete) {
			buff.flip();
			byte[] bytes = new byte[buff.limit()];
			buff.get(bytes);
			String message = new String(bytes, "UTF-8");
			buff.clear();
			if((message.startsWith("<?xml version=\"1.0\"")))
			{
				Object msgObject = mappingMessageObject(message);
				out.write(msgObject);
			}else
			{
				ServerLogger.Error("客户端发送协议不标准:"+message);

			}
		}
		return false;
	}
	*/
	/**  
	 * 返回值的解释：  
	 * 1、false, 继续接收下一批数据，有两种情形，如缓冲区数据刚刚就是一个完整消息，或不够一条消息时。如果不够一条消息，那么会将下一批数据和剩余消息进行合并 
	 * 2、true, 当缓冲区的消息多于一条消息时，剩余消息会再会推送至doDecode 
	 */   
	/*
	protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out)throws Exception {  
		//发送数据时，头四个字节记录了消息的长度。 此方法会读四个字节，并和实现流长度对比。返回前，将流reset.  
		if (in.prefixedDataAvailable(4)) {  
			int length = in.getInt();  
			byte [] bytes =new byte[length];  
			in.get(bytes);  
			ByteArrayInputStream bais =new ByteArrayInputStream(bytes);  
			BufferedImage image = ImageIO.read(bais);  
			out.write(image);  
			return true;//如果读取内容后还粘了包，系统会自动处理。  
		}else{  
			return false;//继续接收数据，以待数据完整  
		}   
	}   
	 */
	/*
	protected boolean doDecode(IoSession session, IoBuffer ioBuffer, ProtocolDecoderOutput out) throws Exception {
	    MsgPack mp = (MsgPack) session.getAttribute("nac-msg-pack"); // 从session对象中获取“xhs-upload”属性值 
	    if(null==mp){
	       if (ioBuffer.remaining() >= 8) {
	         //取消息体长度
	         int msgLength = ioBuffer.getInt(); 
	         int msgMethod = ioBuffer.getInt();
	         mp=new MsgPack();
	         mp.setMsgLength(msgLength);
	         mp.setMsgMethod(msgMethod);
	         session.setAttribute("nac-msg-pack",mp);
	         return true;
	       }
	       return false;
	    }
	    if(ioBuffer.remaining()>=mp.getMsgLength()){
	      byte [] msgPack=new byte[mp.getMsgLength()];
	      ioBuffer.get(msgPack);
	      mp.setMsgPack(new String(msgPack,charset));
	      session.removeAttribute("nac-msg-pack");
	      out.write(mp);
	      return true;
	    }
	    return false;
	  }   

	}
	 */
	
	@Override
	protected boolean doDecode(IoSession iosession, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
		
		if(in.remaining() > 0){//有数据时，读取4字节判断消息长度  
            byte [] sizeBytes = new byte[4];  
            in.mark();//标记当前位置，以便reset  
            in.get(sizeBytes);//读取前4字节  
                        //NumberUtil是自己写的一个int转byte[]的一个工具类  
            int size = NumberUtil.bytes2int(sizeBytes);  
            //如果消息内容的长度不够则直接返回true  
            if(size > in.remaining()){//如果消息内容不够，则重置，相当于不读取size  
                in.reset();  
                return false;//接收新数据，以拼凑成完整数据  
            } else{  
                byte[] bytes = new byte[size];   
                in.get(bytes, 0, size);  
                String xmlStr = new String(bytes,"UTF-8");  
                System.out.println("------------"+xmlStr);  
                if(null != xmlStr && xmlStr.length() > 0){  
                	if((xmlStr.startsWith("<?xml version=\"1.0\"")))
        			{
        				Object msgObject = mappingMessageObject(xmlStr);
        				out.write(msgObject);
        			}else
        			{
        				ServerLogger.Error("客户端发送协议不标准:"+xmlStr);

        			}
                }  
                if(in.remaining() > 0){//如果读取内容后还粘了包，就让父类再给俺  一次，进行下一次解析  
                    return true;  
                }  
            }  
        }  
        return false;//处理成功，让父类进行接收下个包
	}
	
	public void dispose(IoSession arg0) throws Exception
	{

	}

	public void finishDecode(IoSession arg0, ProtocolDecoderOutput arg1)
			throws Exception
	{

	}
	private Object mappingMessageObject(String  message) throws Exception {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
		DocumentBuilder builder = factory.newDocumentBuilder();  
		Document doc = (Document) builder.parse(new ByteArrayInputStream(message.toString().getBytes("UTF-8")));

		String name = doc.getDocumentElement().getTagName();
		/*
		if (name.equals("reply")) {
			RequestBody reply = new RequestBody();
			reply.setKey(doc.getElementsByTagName("key").item(0).getTextContent());
			reply.setCode(doc.getElementsByTagName("code").item(0).getTextContent());
			NodeList items = doc.getElementsByTagName("data").item(0).getChildNodes();  
			for (int i = 0; i < items.getLength(); i++) {  
				Node node = items.item(i);  
				reply.getData().put(node.getNodeName(), node.getTextContent());
			}  
			return reply;
		}
		 */
		if (name.equals("request")) {

			RequestBody body = new RequestBody();
			body.setType(doc.getElementsByTagName("type").item(0).getTextContent());
			body.setSender(doc.getElementsByTagName("sender").item(0).getTextContent());
			body.setReciever(doc.getElementsByTagName("reciever").item(0).getTextContent());
			NodeList items = doc.getElementsByTagName("data").item(0).getChildNodes();  
			for (int i = 0; i < items.getLength(); i++) {  
				Node node = items.item(i);  
				body.getData().put(node.getNodeName(), node.getTextContent());
			}
			body.setTimestamp(Long.valueOf(doc.getElementsByTagName("timestamp").item(0).getTextContent()));
			return body;
		}

		return null;
	}
}
